home *** CD-ROM | disk | FTP | other *** search
- /* $Id: animate.c,v 2.3 89/09/20 17:01:22 mbp Exp $
- *
- * animate.c: animation procedures
- */
-
- /************************************************************************
- * Copyright (C) 1989 by Mark B. Phillips *
- * *
- * Permission to use, copy, modify, and distribute this software and *
- * its documentation for any purpose and without fee is hereby granted, *
- * provided that the above copyright notice appear in all copies and *
- * that both that copyright notice and this permission notice appear in *
- * supporting documentation, and that the name of Mark B. Phillips or *
- * the University of Maryland not be used in advertising or publicity *
- * pertaining to distribution of the software without specific, written *
- * prior permission. This software is provided "as is" without express *
- * or implied warranty. *
- ************************************************************************/
-
- #include <stdio.h>
- #include <signal.h>
-
- #include "gr.h"
- #include "internal.h"
- #include "image_info.h"
-
- /************************************************************************
- * PUBLIC DECLARATIONS *
- ************************************************************************/
-
- Frame GR_anim_frame=NULL;
- Panel GR_anim_panel;
- int GR_interrupted=0;
- int GR_recording_trigger=0;
- int GR_recording_count;
-
- /************************************************************************
- * PRIVATE DECLARATIONS *
- ************************************************************************/
-
- /* Gadgets, etc: */
- static Panel_item save_button, play_button, clear_button;
- static Panel_item save_sequence_button, delay_slider, done_button;
- static Panel_item recording_count_slider, anim_message[2];
- static Panel_item playback_count_slider, frames_saved_message;
- static Panel_item frames_available_message;
- static Menu save_button_menu, save_sequence_button_menu;
- static Menu play_button_menu, clear_button_menu;
-
- /* Maximum number of frames that can be stored at one time: */
- #define MAX_FRAMES 30
-
- /* Array of saved frames (pixrects): */
- static struct pixrect *saved_pr[MAX_FRAMES];
-
- /* Number of currently saved frames: */
- static int frames_saved=0;
-
- /* Images for buttons: */
- static short save_array[] = {
- #include "images/save.image"
- };
- mpr_static(save_pr, VCB_W, VCB_H, 1, save_array);
-
- static short save_sequence_array[] = {
- #include "images/save_sequence.image"
- };
- mpr_static(save_sequence_pr, VCB_W, VCB_H, 1, save_sequence_array);
-
- static short clear_array[] = {
- #include "images/clear.image"
- };
- mpr_static(clear_pr, VCB_W, VCB_H, 1, clear_array);
-
- static short play_array[] = {
- #include "images/play.image"
- };
- mpr_static(play_pr, VCB_W, VCB_H, 1, play_array);
-
- /* Functions: */
- static int button_event_proc(), play_button_proc();
- static int clear_button_proc(), done_button_proc(), save_button_proc();
- static int save_sequence_button_proc(), interrupt_handler();
-
- /*--------------------End of Private Declarations------------------------*/
-
- /************************************************************************
- * PUBLIC PROCEDURES *
- ************************************************************************/
-
- /*-----------------------------------------------------------------------
- * Function: GR_show_anim_frame
- * Description: make the animation frame visible
- * Args: (none)
- */
- int
- GR_show_anim_frame()
- {
- if (GR_anim_frame == NULL) initialize_anim_frame();
- GR_anim_message_clear();
- window_set(GR_anim_frame, WIN_SHOW, TRUE, 0);
- }
-
- /*-----------------------------------------------------------------------
- * Function: GR_show_anim_message
- * Description: display a string in one of the anim panel message lines
- * Args IN: s: the string
- * n: message line to use (0 or 1)
- * Notes: If s is "" the message is cleared
- */
- int
- GR_show_anim_message(s,n)
- int n;
- char *s;
- {
- if ((n<0) || (n>1)) return(1);
- return(GR_show_message(anim_message[n], s, GR_ANIM_MESSAGE_LENGTH));
- }
-
- /*-----------------------------------------------------------------------
- * Function: GR_show_anim_error
- * Description: same as GR_show_anim_message, but beeps bell
- */
- int
- GR_show_anim_error(s,n)
- int n;
- char *s;
- {
- if ((n<0) || (n>1)) return(1);
- window_bell(GR_anim_panel);
- return(GR_show_message(anim_message[n], s, GR_ANIM_MESSAGE_LENGTH));
- }
-
- /*-----------------------------------------------------------------------
- * Function: GR_anim_message_clear
- * Description: clear all messages in anim panel
- */
- int
- GR_anim_message_clear()
- {
- GR_show_anim_message("",0);
- GR_show_anim_message("",1);
- }
-
- /*-----------------------------------------------------------------------
- * Function: GR_save_frame
- * Description: save a frame
- */
- int
- GR_save_frame()
- {
- GR_anim_message_clear();
- if (frames_saved >= MAX_FRAMES) {
- GR_show_anim_error("No more frames available !",0);
- return;
- }
- saved_pr[frames_saved] =
- mem_create(GR_canvas_pw->pw_pixrect->pr_size.x,
- GR_canvas_pw->pw_pixrect->pr_size.y, 1);
- if (saved_pr[frames_saved]==NULL) {
- GR_error("No memory left to store frames !");
- GR_interrupted=1;
- return;
- }
- pw_read(saved_pr[frames_saved], 0, 0,
- saved_pr[frames_saved]->pr_size.x, saved_pr[frames_saved]->pr_size.y,
- PIX_SRC, GR_canvas_pw, 0, 0);
- set_frame_number_displays(++frames_saved);
- }
-
- /************************************************************************
- * PRIVATE PROCEDURES *
- ************************************************************************/
-
- /*-----------------------------------------------------------------------
- * Function: initialize_anim_frame
- * Description: create and initialize animation frame and its subwindows
- * Args: (none)
- */
- static int
- initialize_anim_frame()
- {
- int i;
-
- GR_anim_frame =
- window_create(GR_base_frame, FRAME,
- WIN_X, 462,
- WIN_Y, 0,
- FRAME_SHOW_LABEL, TRUE,
- FRAME_LABEL, "Animation",
- 0);
- if (GR_anim_frame == NULL) {
- GR_error("Can't create any more windows !");
- return(1);
- }
-
- GR_anim_panel =
- window_create(GR_anim_frame, PANEL,
- WIN_X, 0,
- WIN_Y, 0,
- WIN_WIDTH, 370,
- WIN_HEIGHT, 223,
- 0);
- if (GR_anim_panel == NULL) {
- GR_error("Can't create any more windows !");
- window_destroy(GR_anim_frame);
- return(1);
- }
-
- save_button =
- panel_create_item(GR_anim_panel, PANEL_BUTTON,
- PANEL_ITEM_X, 5,
- PANEL_ITEM_Y, 5,
- PANEL_LABEL_IMAGE, &save_pr,
- PANEL_NOTIFY_PROC, save_button_proc,
- PANEL_EVENT_PROC, button_event_proc,
- 0);
- save_button_menu =
- menu_create(MENU_STRINGS, "Save Frame", 0, 0);
-
- play_button =
- panel_create_item(GR_anim_panel, PANEL_BUTTON,
- PANEL_ITEM_X, 5,
- PANEL_ITEM_Y, 111,
- PANEL_LABEL_IMAGE, &play_pr,
- PANEL_NOTIFY_PROC, play_button_proc,
- PANEL_EVENT_PROC, button_event_proc,
- 0);
- play_button_menu =
- menu_create(MENU_STRINGS, "Play Back Saved Frames", 0, 0);
-
- clear_button =
- panel_create_item(GR_anim_panel, PANEL_BUTTON,
- PANEL_ITEM_X, 241,
- PANEL_ITEM_Y, 5,
- PANEL_LABEL_IMAGE, &clear_pr,
- PANEL_NOTIFY_PROC, clear_button_proc,
- PANEL_EVENT_PROC, button_event_proc,
- 0);
- clear_button_menu =
- menu_create(MENU_STRINGS, "Clear Saved Frames", 0, 0);
-
- delay_slider =
- panel_create_item(GR_anim_panel, PANEL_SLIDER,
- PANEL_ITEM_X, 64,
- PANEL_ITEM_Y, 118,
- PANEL_LABEL_STRING, "Interframe Delay (millisecs)",
- PANEL_VALUE, 0,
- PANEL_SLIDER_WIDTH, 100,
- PANEL_MIN_VALUE, 0,
- PANEL_MAX_VALUE, 5000,
- PANEL_LAYOUT, PANEL_VERTICAL,
- 0);
-
- done_button =
- panel_create_item(GR_anim_panel, PANEL_BUTTON,
- PANEL_ITEM_X, 304,
- PANEL_ITEM_Y, 10,
- PANEL_LABEL_IMAGE,
- panel_button_image(GR_anim_panel, "Done", 5, 0),
- PANEL_NOTIFY_PROC, done_button_proc,
- PANEL_EVENT_PROC, button_event_proc,
- 0);
-
- playback_count_slider =
- panel_create_item(GR_anim_panel, PANEL_SLIDER,
- PANEL_ITEM_X, 224,
- PANEL_ITEM_Y, 64,
- PANEL_LABEL_STRING, " Playback Count",
- PANEL_VALUE, 1,
- PANEL_SLIDER_WIDTH, MAX_FRAMES,
- PANEL_MIN_VALUE, 1,
- PANEL_MAX_VALUE, MAX_FRAMES,
- PANEL_LAYOUT, PANEL_VERTICAL,
- 0);
-
- recording_count_slider =
- panel_create_item(GR_anim_panel, PANEL_SLIDER,
- PANEL_ITEM_X, 64,
- PANEL_ITEM_Y, 64,
- PANEL_LABEL_STRING, "Recording Count",
- PANEL_VALUE, 0,
- PANEL_SLIDER_WIDTH, MAX_FRAMES,
- PANEL_MIN_VALUE, 0,
- PANEL_MAX_VALUE, MAX_FRAMES,
- PANEL_LAYOUT, PANEL_VERTICAL,
- 0);
-
- save_sequence_button =
- panel_create_item(GR_anim_panel, PANEL_BUTTON,
- PANEL_ITEM_X, 5,
- PANEL_ITEM_Y, 58,
- PANEL_LABEL_IMAGE, &save_sequence_pr,
- PANEL_NOTIFY_PROC, save_sequence_button_proc,
- PANEL_EVENT_PROC, button_event_proc,
- 0);
- save_sequence_button_menu =
- menu_create(MENU_STRINGS, "Save Sequence of Frames", 0, 0);
-
- anim_message[0] =
- panel_create_item(GR_anim_panel, PANEL_MESSAGE,
- PANEL_ITEM_X, 10,
- PANEL_ITEM_Y, 172,
- PANEL_LABEL_STRING, "",
- PANEL_LABEL_FONT, GR_bold_font,
- 0);
-
- anim_message[1] =
- panel_create_item(GR_anim_panel, PANEL_MESSAGE,
- PANEL_ITEM_X, 10,
- PANEL_ITEM_Y, 195,
- PANEL_LABEL_STRING, "",
- PANEL_LABEL_FONT, GR_bold_font,
- 0);
-
- panel_create_item(GR_anim_panel, PANEL_MESSAGE,
- PANEL_ITEM_X, 95,
- PANEL_ITEM_Y, 7,
- PANEL_LABEL_STRING, "Frames Saved:",
- PANEL_LABEL_BOLD, 0,
- 0);
-
- frames_saved_message =
- panel_create_item(GR_anim_panel, PANEL_MESSAGE,
- PANEL_ITEM_X, 208,
- PANEL_ITEM_Y, 7,
- PANEL_LABEL_STRING, "",
- 0);
-
- panel_create_item(GR_anim_panel, PANEL_MESSAGE,
- PANEL_ITEM_X, 64,
- PANEL_ITEM_Y, 25,
- PANEL_LABEL_STRING, "Frames Available:",
- 0);
-
- frames_available_message =
- panel_create_item(GR_anim_panel, PANEL_MESSAGE,
- PANEL_ITEM_X, 208,
- PANEL_ITEM_Y, 25,
- PANEL_LABEL_STRING, "",
- PANEL_LABEL_BOLD, 0,
- 0);
-
- window_fit(GR_anim_frame);
- set_frame_number_displays(0);
- notify_set_signal_func(GR_base_frame, interrupt_handler,
- SIGURG, NOTIFY_ASYNC);
- for (i=0; i<MAX_FRAMES; ++i)
- saved_pr[i] = NULL;
- }
-
- /*-----------------------------------------------------------------------
- * Function: button_event_proc
- * Description: respond to a button
- * Args IN: item: handle of button which received event
- * event: the event
- * Notes: Display's button's menu if appropriate
- */
- static int
- button_event_proc(item, event)
- Panel_item item;
- Event *event;
- {
- /* If event is right mouse button going down, display button's menu */
- if ( (event_id(event)==MS_RIGHT) && (event_is_down(event)) ) {
-
- if (item == save_sequence_button)
- menu_show(save_sequence_button_menu, GR_anim_panel, event, 0);
- else if (item == save_button)
- menu_show(save_button_menu, GR_anim_panel, event, 0);
- else if (item == play_button)
- menu_show(play_button_menu, GR_anim_panel, event, 0);
- else if (item == clear_button)
- menu_show(clear_button_menu, GR_anim_panel, event, 0);
-
- /* Then move mouse cursor back to where it was before menu display */
- window_set((Panel)panel_get(item, PANEL_PARENT_PANEL),
- WIN_MOUSE_XY, event_x(event), event_y(event),
- 0);
- }
-
- /* Otherwise, do the normal thing for this button */
- else
- panel_default_handle_event(item, event);
- }
-
- /*-----------------------------------------------------------------------
- * Function: save_button_proc
- * Description: save a frame (save button's notify proc)
- */
- static int
- save_button_proc()
- {
- GR_save_frame();
- }
-
- /*-----------------------------------------------------------------------
- * Function: play_button_proc
- * Description: play back saved frames
- */
- static int
- play_button_proc()
- {
- int n, repeat_count, frame;
- unsigned interframe_delay;
- char msg[GR_ANIM_MESSAGE_LENGTH+1];
-
- GR_anim_message_clear();
- if (frames_saved == 0) {
- GR_show_anim_error("No frames have been saved !",0);
- return;
- }
-
- repeat_count = (int)panel_get_value(playback_count_slider);
- interframe_delay = 1000 * (unsigned)panel_get_value(delay_slider);
-
- GR_interrupted=0;
- GR_show_error_message("Hit the STOP key (L1) to interrupt the movie");
- for (n=0; (n<repeat_count) && (!GR_interrupted); ++n) {
- for (frame=0; (frame<frames_saved) && (!GR_interrupted); ++frame) {
- sprintf(msg,"Displaying Frame %2d", frame+1);
- GR_show_anim_message(msg,0);
- pw_batch_on(GR_canvas_pw);
- pw_write(GR_canvas_pw, 0, 0,
- saved_pr[frame]->pr_size.x, saved_pr[frame]->pr_size.y,
- PIX_SRC, saved_pr[frame], 0, 0);
- pw_batch_off(GR_canvas_pw);
- if ((!GR_interrupted) && (interframe_delay != 0))
- usleep(interframe_delay);
- }
- }
- GR_anim_message_clear();
- GR_show_error_message("");
- if (GR_interrupted)
- GR_show_anim_message("Playback interrupted",0);
- else
- GR_show_anim_message("Playback finished",0);
- }
-
- /*-----------------------------------------------------------------------
- * Function: clear_button_proc
- * Description: clear all saved frames
- */
- static int
- clear_button_proc()
- {
- int frame;
-
- GR_anim_message_clear();
- for (frame=0; frame<frames_saved; ++frame) {
- pr_destroy(saved_pr[frame]);
- saved_pr[frame] = NULL;
- }
- set_frame_number_displays(frames_saved=0);
- GR_show_anim_message("Frames cleared",0);
- }
-
- /*-----------------------------------------------------------------------
- * Function: save_sequence_button_proc
- * Description: save a sequence of frames
- * Notes: This proc just sets a flag (GR_recording trigger) and then
- * returns. The view control buttons test for this flag and
- * behave differently if it has been set.
- */
- static int
- save_sequence_button_proc()
- {
- char msg[GR_ANIM_MESSAGE_LENGTH+1];
-
- GR_anim_message_clear();
-
- if (GR_recording_trigger) {
- GR_show_anim_message("Recording sequence canceled",0);
- GR_recording_trigger=0;
- return;
- }
-
- GR_recording_count = (int)panel_get_value(recording_count_slider);
- if (GR_recording_count+frames_saved > MAX_FRAMES) {
- sprintf(msg,"No space for %1d more frames",GR_recording_count);
- GR_show_anim_error(msg,0);
- GR_show_anim_message("(Decrease count or clear frames)",1);
- return;
- }
- GR_recording_trigger=1;
- GR_show_anim_message("Select view button for sequence ...",0);
- GR_show_anim_message("(Pick sequence button again to cancel)",1);
- }
-
- /*-----------------------------------------------------------------------
- * Function: done_button_proc
- * Description: notify procedure for "Done" button
- * Args: (none)
- * Notes: makes animaton frame disappear, but does not destroy it
- */
- static int
- done_button_proc()
- {
- window_set(GR_anim_frame, WIN_SHOW, FALSE, 0);
- }
-
- /*-----------------------------------------------------------------------
- * Function: set_frame_number_displays
- * Description: set the display of the number of saved and available
- * frames
- * Args IN: saved: the number of saved frames
- * Notes: number available is MAX_FRAMES-saved
- */
- static int
- set_frame_number_displays(saved)
- int saved;
- {
- char buf[3];
-
- sprintf(buf, "%2d", saved);
- panel_set(frames_saved_message, PANEL_LABEL_STRING, buf, 0);
- sprintf(buf, "%2d", MAX_FRAMES-saved);
- panel_set(frames_available_message, PANEL_LABEL_STRING, buf, 0);
- }
-
- /*-----------------------------------------------------------------------
- * Function: interrupt_handler
- * Description: handler for SIGURG, which is generate by STOP (L1) key
- * Notes: Just set a flag and return. Other pieces of program
- * check for this flag.
- */
- static int
- interrupt_handler()
- {
- ++GR_interrupted;
- }
-
-